<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Go OTel 应用逻辑解释 - 概述</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
<h1>Go OTel 应用逻辑解释</h1>

<nav>
    <ul>
        <li><a href="index.html" class="active">概述</a></li>
        <li><a href="setup.html">初始化设置</a></li>
        <li><a href="handlers.html">HTTP 处理器</a></li>
        <li><a href="services.html">业务逻辑服务</a></li>
        <li><a href="main_flow.html">主程序流程</a></li>
        <li><a href="glossary.html">名词解释</a></li>
    </ul>
</nav>

<section>
    <h2>程序概述</h2>
    <p>
        这是一个使用 Go 语言编写的简单的 Web 应用程序示例。它演示了如何构建一个包含以下组件的后端服务：
    </p>
    <ul>
        <li><strong>Gin Web 框架:</strong> 用于处理 HTTP 请求和响应。</li>
        <li><strong>GORM (ORM):</strong> 用于与 MySQL 数据库进行交互，简化数据库操作。</li>
        <li><strong>go-redis:</strong> 用于连接 Redis，实现数据缓存以提高性能。</li>
        <li><strong>OpenTelemetry (OTel):</strong> 用于实现分布式追踪，监控请求在系统中的完整路径和性能。</li>
        <li><strong>标准库:</strong> 利用 Go 语言内置的库处理上下文、JSON、错误、并发等。</li>
    </ul>
    <p>
        这个程序提供两个基本的 API 接口：
    </p>
    <ul>
        <li><code>POST /users</code>: 创建一个新用户，保存到 MySQL，并清除相关缓存。</li>
        <li><code>GET /users/{id}</code>: 获取指定 ID 的用户信息，优先从 Redis 缓存读取，缓存未命中则查询 MySQL 并写回缓存。</li>
    </ul>
    <p>
        整个应用的关键在于集成了 OpenTelemetry。这意味着当一个 HTTP 请求进入时，以及在处理过程中调用数据库或 Redis 时，都会自动或手动创建“跨度 (Span)”，这些 Span 链接起来形成一个完整的“追踪 (Trace)”。这有助于我们理解请求的耗时、瓶颈以及不同服务间的调用关系。
    </p>
</section>

<section>
    <h2>高层逻辑流程图</h2>
    <div class="diagram">
        <svg width="700" height="450" xmlns="http://www.w3.org/2000/svg">
            <!-- 定义箭头 -->
            <defs>
                <marker id="arrowhead" markerWidth="10" markerHeight="7" refX="0" refY="3.5" orient="auto">
                    <polygon points="0 0, 10 3.5, 0 7" fill="#6c757d" />
                </marker>
            </defs>

            <!-- 组件 -->
            <rect x="50" y="180" width="100" height="60" class="svg-rect"/>
            <text x="100" y="215" class="svg-text">客户端</text>
            <text x="100" y="195" class="svg-text">(浏览器/curl)</text>

            <rect x="200" y="180" width="120" height="60" class="svg-rect"/>
            <text x="260" y="205" class="svg-text">Gin Web 服务器</text>
            <text x="260" y="225" class="svg-text">(含 OTel 中间件)</text>

            <rect x="370" y="180" width="120" height="60" class="svg-rect"/>
            <text x="430" y="200" class="svg-text">HTTP 处理器</text>
            <text x="430" y="220" class="svg-text">(Handler)</text>
            <text x="430" y="235" class="svg-text">(创建 Handler Span)</text>

            <rect x="540" y="180" width="120" height="60" class="svg-rect"/>
            <text x="600" y="200" class="svg-text">业务逻辑服务</text>
            <text x="600" y="220" class="svg-text">(Service)</text>
            <text x="600" y="235" class="svg-text">(创建 Service Span)</text>

            <rect x="460" y="320" width="100" height="60" class="svg-rect"/>
            <text x="510" y="345" class="svg-text">Redis 缓存</text>
            <text x="510" y="365" class="svg-text">(redisotel)</text>

            <rect x="620" y="320" width="100" height="60" class="svg-rect"/>
            <text x="670" y="345" class="svg-text">MySQL DB</text>
            <text x="670" y="365" class="svg-text">(otelgorm)</text>

            <!-- OTel Layer -->
            <rect x="180" y="50" width="560" height="350" rx="10" ry="10" style="fill:none; stroke:#adb5bd; stroke-width:2; stroke-dasharray: 5,5;"/>
            <text x="460" y="35" class="svg-text" style="font-weight:bold; fill:#0056b3;">OpenTelemetry 追踪层 (贯穿始终)</text>
            <line x1="260" y1="180" x2="260" y2="70" class="svg-line" />
            <line x1="430" y1="180" x2="430" y2="70" class="svg-line" />
            <line x1="600" y1="180" x2="600" y2="70" class.svg-line" />
            <line x1="510" y1="320" x2="510" y2="70" class="svg-line" />
            <line x1="670" y1="320" x2="670" y2="70" class="svg-line" />
            <text x="460" y="80" class="svg-text" style="font-size:11px;">(所有交互被 OTel 记录为 Spans)</text>


            <!-- 箭头 -->
            <line x1="150" y1="210" x2="200" y2="210" class="svg-arrow"/>
            <text x="175" y="200" class="svg-label">HTTP 请求</text>

            <line x1="320" y1="210" x2="370" y2="210" class="svg-arrow"/>

            <line x1="490" y1="210" x2="540" y2="210" class="svg-arrow"/>
            <text x="515" y="200" class="svg-label">调用</text>

            <!-- Service to DB/Redis -->
            <path d="M 580 240 Q 580 280 540 320" fill="none" class="svg-arrow"/>
            <text x="575" y="285" class="svg-label">查/写缓存</text>

            <path d="M 620 240 Q 620 280 640 320" fill="none" class="svg-arrow"/>
            <text x="635" y="285" class="svg-label">查/写数据库</text>
        </svg>
        <p style="margin-top: 10px; font-style: italic; color: #6c757d;">
            上图展示了请求的基本流程和 OpenTelemetry 如何贯穿各个组件进行监控。
        </p>
    </div>
</section>

<section>
    <h2>下一步</h2>
    <p>
        请使用导航栏按顺序浏览其他页面，深入了解每个部分的具体实现和逻辑：
    </p>
    <ul>
        <li><a href="setup.html">初始化设置</a>: 了解 OTel、数据库和 Redis 是如何配置和启动的。</li>
        <li><a href="handlers.html">HTTP 处理器</a>: 查看 Gin 如何接收请求并将其分发给处理函数。</li>
        <li><a href="services.html">业务逻辑服务</a>: 探索核心的用户查找和保存逻辑，包括缓存策略。</li>
        <li><a href="main_flow.html">主程序流程</a>: 理解整个应用的启动、运行和关闭过程。</li>
        <li><a href="glossary.html">名词解释</a>: 随时查阅不熟悉的术语。</li>
    </ul>
</section>

</body>
</html>